using System;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using Habanero.Smooth;
using Habanero.Testability;
using Habanero.Testability.Helpers;
using NUnit.Framework;

namespace Firestarter.Test.Base.BusinessObjectMerger
{
    [TestFixture]
    public class TestMergeBO
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            ClassDef.ClassDefs.Clear();
            AllClassesAutoMapper.ClassDefCol = ClassDef.ClassDefs;
            ClassDefCol classDefCol = typeof(FakeMergeableParent).Assembly.MapClasses();
            ClassDef.ClassDefs.Add(classDefCol);
        }

        [SetUp]
        public virtual void SetupTest()
        {
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }


        [Test]
        public void Test_ConstructShouldCreateMergeBo()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IMergeBO mergeBO = new MergeBO<MockBo>();
            //---------------Test Result -----------------------
            Assert.IsNotNull(mergeBO);
        }

        [Test]
        public void Test_MergeBOFrom_WhenToBusinessObjectNull_ShouldCreateBO_AndCopyAllProperties()
        {
            //---------------Set up test pack-------------------
            IMergeBO<MockBo> mergeBO = new MergeBO<MockBo>();
            MockBo fromBO = new MockBo
            {
                TestStringProp = GetRandomString()
            };
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var toBO = mergeBO.MergeBOFrom(fromBO, null);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toBO);
            Assert.AreEqual(fromBO.TestStringProp, toBO.TestStringProp);
        }

        [Test]
        public void Test_MergeBOFrom_ShouldNotMergeIDProp()
        {
            //---------------Set up test pack-------------------
            IMergeBO<MockBo> mergeBO = new MergeBO<MockBo>();
            MockBo fromBO = new MockBo();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var toBO = mergeBO.MergeBOFrom(fromBO, null);
            //---------------Test Result -----------------------
            Assert.AreNotEqual(fromBO.IdProp, toBO.IdProp);
        }

        [Test]
        public void Test_CreateBO_ShouldCreateNewBOOfCorrectType()
        {
            //---------------Set up test pack-------------------
            IMergeBO<MockBo> mergeBO = new MergeBO<MockBo>();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var createdBO = mergeBO.CreateBusinessObject();
            //---------------Test Result -----------------------
            Assert.IsNotNull(createdBO);
        }

        [Test]
        public void Test_FindBusinessObject_WhenToStringsAreSame_ShouldFind()
        {
            //---------------Set up test pack-------------------
            MergeBO<MockBo2> mergeBO = new MergeBO<MockBo2>();
            MockBo2 boToFind = new MockBo2
            {
                TestStringProp = GetRandomString()
            };
            MockBo2 expectedFoundBO = new MockBo2
            {
                TestStringProp = boToFind.TestStringProp
            };
            var bos = new FakeBusinessObjectCollection<MockBo2> { expectedFoundBO };
            //---------------Assert Precondition----------------
            Assert.AreEqual(boToFind.TestStringProp, expectedFoundBO.TestStringProp);
            Assert.AreEqual(boToFind.ToString(), expectedFoundBO.ToString());
            //---------------Execute Test ----------------------
            var foundBO = mergeBO.FindBusinessObject(bos, boToFind);
            //---------------Test Result -----------------------
            Assert.AreSame(expectedFoundBO, foundBO);
        }

        [Test]
        public void Test_MergeBOFrom_WhenToBusinessObjectNotNull_ShouldCopyAllProperties()
        {
            //---------------Set up test pack-------------------
            IMergeBO<MockBo> mergeBO = new MergeBO<MockBo>();
            MockBo fromBO = new MockBo
            {
                TestStringProp = GetRandomString()
            };
            var expectedToBO = new MockBo();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var toBO = mergeBO.MergeBOFrom(fromBO, expectedToBO);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toBO);
            Assert.AreSame(expectedToBO, toBO);
            Assert.AreEqual(fromBO.TestStringProp, toBO.TestStringProp);
        }

        [Test]
        public void Test_FindBusinessObject_WhenToStringsAreNotSame_ShouldNotFind()
        {
            //---------------Set up test pack-------------------
            MergeBO<MockBo2> mergeBO = new MergeBO<MockBo2>();
            MockBo2 boToFind = new MockBo2
            {
                TestStringProp = GetRandomString()
            };
            MockBo2 expectedFoundBO = new MockBo2
            {
                TestStringProp = GetRandomString()
            };
            var bos = new FakeBusinessObjectCollection<MockBo2> { expectedFoundBO };
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(boToFind.TestStringProp, expectedFoundBO.TestStringProp);
            Assert.AreNotEqual(boToFind.ToString(), expectedFoundBO.ToString());
            //---------------Execute Test ----------------------
            var foundBO = mergeBO.FindBusinessObject(bos, boToFind);
            //---------------Test Result -----------------------
            Assert.IsNull(foundBO);
        }

        [TestCase(ChangeType.None, ChangeType.None, ChangeType.None, ChangeType.None)]
        [TestCase(ChangeType.Delete, ChangeType.None, ChangeType.Delete, ChangeType.Update)]
        [TestCase(ChangeType.Add, ChangeType.None, ChangeType.Add, ChangeType.Update)]
        [TestCase(ChangeType.Update, ChangeType.None, ChangeType.Update, ChangeType.Update)]
        [TestCase(ChangeType.Rename, ChangeType.None, ChangeType.Rename, ChangeType.Update)]
        public void Test_UpdatePendingChangeType_WhenMultipleRelationship_WhenMustMergeRelationshipTrue(ChangeType initialChildChangeType, ChangeType initialParentChangeType, ChangeType expectedChildChangeType, ChangeType expectedParentChangeType)
        {
            //---------------Set up test pack-------------------
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableParent>();

            var parentBO = GetFactory()
                .WithOne(columnLayout => columnLayout.FakeMergeables)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            parentBO.Save();
            IMergableBo child = parentBO.FakeMergeables[0];
            IMergableBo parent = parentBO;
            parent.PendingChangeType = initialParentChangeType;
            child.PendingChangeType = initialChildChangeType;

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, parentBO.FakeMergeables.Count);
            Assert.AreEqual(initialChildChangeType, child.PendingChangeType);
            Assert.AreEqual(initialParentChangeType, parent.PendingChangeType);
            Assert.IsFalse(parent.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(parentBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedChildChangeType, child.PendingChangeType, GetMessage(initialParentChangeType, initialChildChangeType));
            Assert.AreEqual(expectedParentChangeType, parent.PendingChangeType, GetMessage(initialParentChangeType, initialChildChangeType));
        }
/*        [TestCase(ChangeType.None, ChangeType.None, false)]
        [TestCase(ChangeType.Delete, ChangeType.None, true)]
        [TestCase(ChangeType.Add, ChangeType.None, true)]
        [TestCase(ChangeType.Update, ChangeType.None, true)]
        [TestCase(ChangeType.Rename, ChangeType.None, true)]
        public void Test_UpdatePendingChangeType_WhenMultipleRelationship_WhenMustMergeRelationshipTrue(ChangeType initialChildChangeType, ChangeType initialParentChangeType, bool pendingChangeTypeApproved)
        {
            //---------------Set up test pack-------------------
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableParent>();

            var parentBO = GetFactory()
                .WithOne(columnLayout => columnLayout.FakeMergeables)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            parentBO.Save();
            IMergableBo child = parentBO.FakeMergeables[0];
            IMergableBo parent = parentBO;
            parent.PendingChangeType = initialParentChangeType;
            child.PendingChangeType = initialChildChangeType;

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, parentBO.FakeMergeables.Count);
            Assert.AreEqual(initialChildChangeType, child.PendingChangeType);
            Assert.AreEqual(initialParentChangeType, parent.PendingChangeType);
            Assert.IsFalse(parent.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(parentBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(pendingChangeTypeApproved, parent.PendingChangeApproved, GetMessage(initialParentChangeType, initialChildChangeType) + " Parent PendingChangeApproved should be true");
            //Assert.AreEqual(pendingChangeTypeApproved, child.PendingChangeApproved, GetMessage(initialParentChangeType, initialChildChangeType) + " Child PendingChangeApproved should be true");
        }*/

        [TestCase(ChangeType.None, ChangeType.None, ChangeType.None, ChangeType.None)]
        [TestCase(ChangeType.Delete, ChangeType.None, ChangeType.Delete, ChangeType.Update)]
        [TestCase(ChangeType.Add, ChangeType.None, ChangeType.Add, ChangeType.Update)]
        [TestCase(ChangeType.Update, ChangeType.None, ChangeType.Update, ChangeType.Update)]
        [TestCase(ChangeType.Rename, ChangeType.None, ChangeType.Rename, ChangeType.Update)]
        public void Test_UpdatePendingChangeType_WhenSingleRelationship_WhenMustMergeRelationshipTrue(ChangeType initialChildChangeType, ChangeType initialParentChangeType, ChangeType expectedChildChangeType, ChangeType expectedParentChangeType)
        {
            //---------------Set up test pack-------------------
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableParent>();
            var childBO = new FakeMergeableChild();
            var parentBO = new FakeMergeableParent();
            parentBO.FakeMergeableChild = childBO;
            parentBO.Save();
            IMergableBo child = childBO;
            IMergableBo parent = parentBO;
            parent.PendingChangeType = initialParentChangeType;
            child.PendingChangeType = initialChildChangeType;

            //---------------Assert Precondition----------------
            Assert.AreSame(childBO, parentBO.FakeMergeableChild);
            Assert.AreEqual(initialChildChangeType, child.PendingChangeType);
            Assert.AreEqual(initialParentChangeType, parent.PendingChangeType);
            Assert.IsFalse(parent.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(parentBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedParentChangeType, parent.PendingChangeType, GetMessage(initialParentChangeType, initialChildChangeType));
            Assert.AreEqual(expectedChildChangeType, child.PendingChangeType, GetMessage(initialParentChangeType, initialChildChangeType));
        }

   /*     [TestCase(ChangeType.None, ChangeType.None, false)]
        [TestCase(ChangeType.Delete, ChangeType.None, true)]
        [TestCase(ChangeType.Add, ChangeType.None, true)]
        [TestCase(ChangeType.Update, ChangeType.None, true)]
        [TestCase(ChangeType.Rename, ChangeType.None, true)]
        public void Test_UpdatePendingChangeType_WhenSingleRelationship_WhenMustMergeRelationshipTrue(ChangeType initialChildChangeType, ChangeType initialParentChangeType, bool pendingChangeTypeApproved)
        {
            //---------------Set up test pack-------------------
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableParent>();
            var childBO = new FakeMergeableChild();
            var parentBO = new FakeMergeableParent();
            parentBO.FakeMergeableChild = childBO;
            parentBO.Save();
            IMergableBo child = childBO;
            IMergableBo parent = parentBO;
            parent.PendingChangeType = initialParentChangeType;
            child.PendingChangeType = initialChildChangeType;

            //---------------Assert Precondition----------------
            Assert.AreSame(childBO, parentBO.FakeMergeableChild);
            Assert.AreEqual(initialChildChangeType, child.PendingChangeType);
            Assert.AreEqual(initialParentChangeType, parent.PendingChangeType);
            Assert.IsFalse(parent.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(parentBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(pendingChangeTypeApproved, parent.PendingChangeApproved, GetMessage(initialParentChangeType, initialChildChangeType) + " Parent PendingChangeApproved should be true");
            // Assert.AreEqual(pendingChangeTypeApproved, child.PendingChangeApproved, GetMessage(initialParentChangeType, initialChildChangeType) + " Child PendingChangeApproved should be true");
        }*/

        public static BOTestFactory<FakeMergeableParent> GetFactory()
        {
            return BOTestFactoryRegistry.Instance.Resolve<FakeMergeableParent>();
        }


        private string GetMessage(ChangeType initialParentChangeType, ChangeType initialChildChangeType)
        {
            return "When ChildChangeType is " + initialChildChangeType + " And ParentChangeType = " + initialParentChangeType;
        }
        /// <summary>
        /// Must ensure that entire project is saved prior to startingMerge so that dirty is a reliable indicator of the Object having been updated.
        /// </summary>
        [Test]
        public void Test_UpdatePendingChangeType_WhenBOIsDirty_AndChangeTypeNone_ShouldChangeToUpdated()
        {
            //---------------Set up test pack-------------------
            ClassDef.ClassDefs.Add(typeof(FakeMergeableChild).MapClass());
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableChild>();

            var mockBO = new FakeMergeableChild();
            mockBO.Save();
            mockBO.TestStringProp = RandomValueGen.GetRandomString();
            IMergableBo mergableBo = mockBO;
            mergableBo.PendingChangeType = ChangeType.None;
            //---------------Assert Precondition----------------
            Assert.AreEqual(ChangeType.None, mergableBo.PendingChangeType);
            Assert.IsTrue(mockBO.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(mockBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(ChangeType.Update, mergableBo.PendingChangeType);
            Assert.IsTrue(mockBO.Status.IsDirty);
        }

        [Test]
        public void Test_UpdatePendingChangeType_WhenBOIsNotDirty_AndChangeTypeNone_ShouldNotChange()
        {
            //---------------Set up test pack-------------------
            ClassDef.ClassDefs.Add(typeof(FakeMergeableChild).MapClass());
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableChild>();
            var mockBO = new FakeMergeableChild();
            mockBO.Save();
            IMergableBo mergableBo = mockBO;
            mergableBo.PendingChangeType = ChangeType.None;
            //---------------Assert Precondition----------------
            Assert.AreEqual(ChangeType.None, mergableBo.PendingChangeType);
            Assert.IsFalse(mockBO.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(mockBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(ChangeType.None, mergableBo.PendingChangeType);
            Assert.IsFalse(mockBO.Status.IsDirty);
        }

        [Test]
        public void Test_UpdatePendingChangeType_WhenBOIsDirty_AndChangeTypeAdd_ShouldNotChange()
        {
            //---------------Set up test pack-------------------
            ClassDef.ClassDefs.Add(typeof(FakeMergeableChild).MapClass());
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableChild>();
            var mockBO = new FakeMergeableChild();
            mockBO.Save();
            mockBO.TestStringProp = RandomValueGen.GetRandomString();
            IMergableBo mergableBo = mockBO;
            mergableBo.PendingChangeType = ChangeType.Add;
            //---------------Assert Precondition----------------
            Assert.AreEqual(ChangeType.Add, mergableBo.PendingChangeType);
            Assert.IsTrue(mockBO.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(mockBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(ChangeType.Add, mergableBo.PendingChangeType);
            Assert.IsTrue(mockBO.Status.IsDirty);
        }
        [Test]
        public void Test_UpdatePendingChangeType_WhenBOIsDirty_ShouldSetPendingChangeToUpdate()
        {
            //---------------Set up test pack-------------------
            ClassDef.ClassDefs.Add(typeof(FakeMergeableChild).MapClass());
            var merger = MergeableBORegistry.Instance.Resolve<FakeMergeableChild>();
            var mockBO = new FakeMergeableChild();
            mockBO.Save();
            mockBO.TestStringProp = RandomValueGen.GetRandomString();
            IMergableBo mergableBo = mockBO;
            //---------------Assert Precondition----------------
            Assert.AreEqual("0", mergableBo.PendingChangeType.ToString());
            Assert.IsTrue(mockBO.Status.IsDirty);
            //---------------Execute Test ----------------------
            merger.UpdatePendingChangeType(mockBO);
            //---------------Test Result -----------------------
            Assert.AreEqual(ChangeType.Update, mergableBo.PendingChangeType);
           // Assert.IsTrue(mockBO.PendingChangeApproved, "Should Approve all changes by default");
        }

        [Test]
        public void Test_MustTraverserRelationship_WhenAssociation_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            var fromPropRule = new FakeMergeableChild();
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var dmPropertyRelationship = fromPropRule.Relationships["FakeMergeableParentReverse"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(Habanero.Base.RelationshipType.Association, dmPropertyRelationship.RelationshipDef.RelationshipType);
            //---------------Execute Test ----------------------
            var mustTraverseRelationship = mergeBO.MustMergeRelationship(dmPropertyRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustTraverseRelationship);
        }

        [Test]
        public void Test_MustTraverserRelationship_WhenComposition_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            var fromPropRule = new FakeMergeableParent();
            MergeBO<FakeMergeableParent> mergeBO = new MergeBO<FakeMergeableParent>();
            var associationRelationship = fromPropRule.Relationships["FakeCompositionMergeables"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(Habanero.Base.RelationshipType.Composition, associationRelationship.RelationshipDef.RelationshipType);
            //---------------Execute Test ----------------------
            var mustTraverseRelationship = mergeBO.MustMergeRelationship(associationRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(mustTraverseRelationship);
        }
        private static string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }

/*

        [Test]
        public void Test_MustTraverserRelationship_WhenAssociation_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            var fromPropRule = new DMPropRule();
            MergeBO<DMPropRule> mergeBO = new MergeBO<DMPropRule>();
            var dmPropertyRelationship = fromPropRule.Relationships["DMProperty"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(Habanero.Base.RelationshipType.Association, dmPropertyRelationship.RelationshipDef.RelationshipType);
            //---------------Execute Test ----------------------
            var mustTraverseRelationship = mergeBO.MustMergeRelationship(dmPropertyRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustTraverseRelationship);
        }

        [Test]
        public void Test_MustTraverserRelationship_WhenComposition_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            var fromPropRule = new DMPropRule();
            MergeBO<DMPropRule> mergeBO = new MergeBO<DMPropRule>();
            var dmPropRuleParameters = fromPropRule.Relationships["PropRuleParameters"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(Habanero.Base.RelationshipType.Composition, dmPropRuleParameters.RelationshipDef.RelationshipType);
            //---------------Execute Test ----------------------
            var mustTraverseRelationship = mergeBO.MustMergeRelationship(dmPropRuleParameters);
            //---------------Test Result -----------------------
            Assert.IsTrue(mustTraverseRelationship);
        }
*/

        [Test]
        public void Test_MustMergeProperty_WhenPropIsString_ShouldRetTrue()
        {
            //---------------Set up test pack-------------------
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var propRule = new FakeMergeableChild();
            IBOProp boProp = propRule.Props["TestStringProp"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(typeof(string), boProp.PropertyType);
            //---------------Execute Test ----------------------
            bool mustMergeProperty = mergeBO.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsTrue(mustMergeProperty);
        }
        [Test]
        public void Test_MustMergeProperty_WhenPropIsGuid_ShouldRetFalse()
        {
            //---------------Set up test pack-------------------
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var propRule = new FakeMergeableChild();
            IBOProp boProp = propRule.Props["FakeMergeableChildID"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(typeof(Guid), boProp.PropertyType);
            //---------------Execute Test ----------------------
            bool mustMergeProperty = mergeBO.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustMergeProperty);
        }

        [Test]
        public void Test_MustMergeProperty_WhenPropTypIsChangeType_ShouldRetFalse()
        {
            //---------------Set up test pack-------------------
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var propRule = new FakeMergeableChild();
            IBOProp boProp = propRule.Props["PendingChangeType"];
            //---------------Assert Precondition----------------
            Assert.AreEqual(typeof(ChangeType), boProp.PropertyType);
            //---------------Execute Test ----------------------
            bool mustMergeProperty = mergeBO.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustMergeProperty);
        }

        [Test]
        public void Test_MustMergeProperty_WhenPropIsGenerated_ShouldRetFalse()
        {
            //---------------Set up test pack-------------------
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var propRule = new FakeMergeableChild();
            IBOProp boProp = propRule.Props["Generated"];
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            bool mustMergeProperty = mergeBO.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustMergeProperty);
        }
        [Test]
        public void Test_MustMergeProperty_WhenPropIsGenerateCode_ShouldRetFalse()
        {
            //---------------Set up test pack-------------------
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var propRule = new FakeMergeableChild();
            IBOProp boProp = propRule.Props["GenerateCode"];
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            bool mustMergeProperty = mergeBO.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustMergeProperty);
        }
        [Test]
        public void Test_MustMergeProperty_WhenPropIsNeedsRegeneration_ShouldRetFalse()
        {
            //---------------Set up test pack-------------------
            MergeBO<FakeMergeableChild> mergeBO = new MergeBO<FakeMergeableChild>();
            var propRule = new FakeMergeableChild();
            IBOProp boProp = propRule.Props["NeedsRegeneration"];
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            bool mustMergeProperty = mergeBO.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustMergeProperty);
        }

    }



    public class FakeMergeableChild : BusinessObject, IMergableBo
    {
        public ChangeType PendingChangeType { get; set; }

        public bool PendingChangeApproved { get; set; }
        public string TestStringProp
        {
            get { return (string)GetPropertyValue("TestStringProp"); }
            set { SetPropertyValue("TestStringProp", value); }
        }
        public bool GenerateCode
        {
            get { return (bool)GetPropertyValue("GenerateCode"); }
            set { SetPropertyValue("GenerateCode", value); }
        }
        public bool NeedsRegeneration
        {
            get { return (bool)GetPropertyValue("NeedsRegeneration"); }
            set { SetPropertyValue("NeedsRegeneration", value); }
        }

        public bool Generated { get; set; }

        [AutoMapOneToOne("FakeMergeableChild", RelationshipType.Association)]
        public virtual FakeMergeableParent FakeMergeableParentReverse
        {
            get
            {
                return Relationships.GetRelatedObject<FakeMergeableParent>("FakeMergeableParentReverse");
            }
            set
            {
                Relationships.SetRelatedObject("FakeMergeableParentReverse", value);
            }
        }
    }

    public class FakeMergeableParent : BusinessObject, IMergableBo
    {
        public ChangeType PendingChangeType { get; set; }

        public bool PendingChangeApproved { get; set; }
        public string TestParentProp
        {
            get { return (string)GetPropertyValue("TestParentProp"); }
            set { SetPropertyValue("TestParentProp", value); }
        }

        [AutoMapOneToOne("FakeMergeableParentReverse", RelationshipType.Aggregation)]
        public virtual FakeMergeableChild FakeMergeableChild
        {
            get
            {
                return Relationships.GetRelatedObject<FakeMergeableChild>("FakeMergeableChild");
            }
            set
            {
                Relationships.SetRelatedObject("FakeMergeableChild", value);
            }
        }

        [AutoMapOneToOne("FakeMergeableParentCompisitionReverse", RelationshipType.Composition)]
        public virtual FakeMergeableChild FakeMergeableCompositionChild
        {
            get
            {
                return Relationships.GetRelatedObject<FakeMergeableChild>("FakeMergeableCompositionChild");
            }
            set
            {
                Relationships.SetRelatedObject("FakeMergeableCompositionChild", value);
            }
        }


        [AutoMapOneToMany(RelationshipType = RelationshipType.Aggregation)]
        public virtual BusinessObjectCollection<FakeMergeableChild> FakeMergeables
        {
            get
            {
                return Relationships.GetRelatedCollection<FakeMergeableChild>("FakeMergeables");
            }
        }
        [AutoMapOneToMany(RelationshipType = RelationshipType.Composition, ReverseRelationshipName = "CompositionRev")]
        public virtual BusinessObjectCollection<FakeMergeableChild> FakeCompositionMergeables
        {
            get
            {
                return Relationships.GetRelatedCollection<FakeMergeableChild>("FakeCompositionMergeables");
            }
        }
    }

    public class FakeBOWithOneToOneAssociationRel: BusinessObject, IMergableBo
    {

        public new static IClassDef LoadDefaultClassDef()
        {
            XmlClassLoader itsLoader = new XmlClassLoader(new DtdLoader(), new DefClassFactory());
            IClassDef itsClassDef = itsLoader.LoadClass(@"
			  <class name=""FakeBOWithWithOneToOneAssociationRel"" assembly=""Firestarter.Test.Base.BusinessObjectMerger"">
			    <property name=""FakeBOWithWithOneToONeAssociationRelID"" type=""Guid"" compulsory=""true"" />
			    <primaryKey>
			      <prop name=""FakeBOWithWithOneToONeAssociationRelID"" />
			    </primaryKey>
			    <relationship name=""FakeMergeableParentReverse"" type=""single"" relatedClass=""FakeBO2WithOneToOneAssociationRel"" relatedAssembly=""Firestarter.Test.Base.BusinessObjectMerger"">
			      <relatedProperty property=""FakeBOWithWithOneToONeAssociationRelID"" relatedProperty=""FakeBOWithWithOneToONeAssociationRelID"" />
			    </relationship>
			  </class>
			");
            ClassDef.ClassDefs.Add(itsClassDef);
            return itsClassDef;
        }
        public ChangeType PendingChangeType { get; set; }

        public bool PendingChangeApproved { get; set; }
    //    public Guid? FakeBO2WithOneToOneAssociationRelID { get; set; }

        public virtual FakeBO2WithOneToOneAssociationRel FakeMergeableParentReverse
        {
            get
            {
                return Relationships.GetRelatedObject<FakeBO2WithOneToOneAssociationRel>("FakeMergeableParentReverse");
            }
            set
            {
                Relationships.SetRelatedObject("FakeMergeableParentReverse", value);
            }
        }
    }
    public class FakeBO2WithOneToOneAssociationRel : BusinessObject, IMergableBo
    {
        public new static IClassDef LoadDefaultClassDef()
        {
            XmlClassLoader itsLoader = new XmlClassLoader(new DtdLoader(), new DefClassFactory());
            IClassDef itsClassDef = itsLoader.LoadClass(@"
			  <class name=""FakeBO2WithOneToOneAssociationRel"" assembly=""Firestarter.Test.Base.BusinessObjectMerger"">
			    <property name=""FakeBO2WithOneToOneAssociationRelID"" type=""Guid"" compulsory=""true"" />
			    <property name=""FakeBOWithWithOneToONeAssociationRelID"" type=""Guid"" compulsory=""true"" />
			    <primaryKey>
			      <prop name=""FakeBO2WithOneToOneAssociationRelID"" />
			    </primaryKey>
			    <relationship name=""FakeMergeableRel"" type=""single"" relatedClass=""FakeBOWithWithOneToOneAssociationRel"" relatedAssembly=""Firestarter.Test.Base.BusinessObjectMerger"">
			      <relatedProperty property=""FakeBOWithWithOneToONeAssociationRelID"" relatedProperty=""FakeBOWithWithOneToONeAssociationRelID"" />
			    </relationship>
			  </class>
			");
            ClassDef.ClassDefs.Add(itsClassDef);
            return itsClassDef;
        }
        public ChangeType PendingChangeType { get; set; }

        public bool PendingChangeApproved { get; set; }


/*
        public virtual Guid? FakeBOWithWithOneToONeAssociationRelID
        {
            get
            {
                return ((Guid?)(base.GetPropertyValue("FakeBOWithWithOneToONeAssociationRelID")));
            }
            set
            {
                base.SetPropertyValue("FakeBOWithWithOneToONeAssociationRelID", value);
            }
        }

        public virtual Guid? FakeBO2WithOneToOneAssociationRelID
        {
            get
            {
                return ((Guid?)(base.GetPropertyValue("FakeBO2WithOneToOneAssociationRelID")));
            }
            set
            {
                base.SetPropertyValue("FakeBO2WithOneToOneAssociationRelID", value);
            }
        }*/
        public virtual FakeBOWithOneToOneAssociationRel FakeMergeableRel
        {
            get
            {
                return Relationships.GetRelatedObject<FakeBOWithOneToOneAssociationRel>("FakeMergeableRel");
            }
            set
            {
                Relationships.SetRelatedObject("FakeMergeableRel", value);
            }
        }

    }


}